package com.baor.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baor.dao.FinanceDao;
import com.baor.dao.MoneyDao;
import com.baor.dao.OrderDao;
import com.baor.dao.VipDao;
import com.baor.domain.FinanceVo;
import com.baor.domain.MoneyVo;
import com.baor.domain.OrderVo;
import com.baor.domain.UserVo;
import com.baor.enums.FuncEnum;
import com.baor.service.FinanceService;
import com.baor.utils.AjaxResult;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.baor.utils.DateUtil.now;

@Service
public class FinanceServiceImpl implements FinanceService {

    @Autowired
    private FinanceDao financeDao;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private VipDao userDao;

    @Autowired
    private MoneyDao moneyDao;

    @Override
    public AjaxResult<?> financialStatementList(Map<String, Object> params) {
        params.put("pageIndex", (int) params.get("pageSize") * ((int) (params.get("pageIndex")) - 1));
        params.put("pageSize", params.get("pageSize"));
        Map<String, Object> res = new HashMap<>();
        res.put("userList", financeDao.financialStatementList(params));
        res.put("pageCount", financeDao.pageCount(params));
        // update top
        //累计收款 - 订单金额总和
        //累计退款 -
        //累计转账 - 累计提现 -
        BigDecimal total = orderDao.selectList(new LambdaQueryWrapper<OrderVo>().eq(OrderVo::getSiteId, params.get("siteId")))
                .stream().map(x -> x.getOrderRealAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
        List<FinanceVo> list = financeDao.selectList(new LambdaQueryWrapper<FinanceVo>().eq(FinanceVo::getSiteId, params.get("siteId")).in(FinanceVo::getFinanceStatus,1,2));
        BigDecimal zhuanzhang = list.stream().filter(x -> x.getFinanceType().equals("1")).map(x -> x.getFinalMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal tuikuan = list.stream().filter(x -> x.getFinanceType().equals("2")).map(x -> x.getFinalMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);
        res.put("total",total);
        res.put("tuikuan",tuikuan);
        res.put("zhuanzhang",zhuanzhang);
        return AjaxResult.success(res);
    }

    @Override
    public AjaxResult<?> getFinanceById(Integer financeId) {
        FinanceVo financeVo = financeDao.selectById(financeId);
        return AjaxResult.success(financeVo);
    }

    @Override
    public AjaxResult<?> withdrawalList(Map<String, Object> params) {
        params.put("pageIndex", (int) params.get("pageSize") * ((int) (params.get("pageIndex")) - 1));
        params.put("pageSize", params.get("pageSize"));
        Map<String, Object> res = new HashMap<>();
        res.put("userList", financeDao.withdrawalList(params));
        res.put("pageCount", financeDao.pageCount2(params));
        List<FinanceVo> list = financeDao.
                selectList(new LambdaQueryWrapper<FinanceVo>()
                        .eq(FinanceVo::getSiteId, params.get("siteId"))
                        .eq(FinanceVo::getFinanceType,1));//提现
        res.put("had",list.stream().filter(x -> x.getFinanceStatus().equals("3")).map(x -> x.getFinalMoney()).reduce(BigDecimal.ZERO,BigDecimal::add));
        res.put("in",list.stream().filter(x -> x.getFinanceStatus().equals("1") || x.getFinanceStatus().equals("2")).map(x -> x.getFinalMoney()).reduce(BigDecimal.ZERO,BigDecimal::add));
        return AjaxResult.success(res);
    }

    @Override
    public AjaxResult<?> backList(Map<String, Object> params) {
        params.put("pageIndex", (int) params.get("pageSize") * ((int) (params.get("pageIndex")) - 1));
        params.put("pageSize", params.get("pageSize"));
        Map<String, Object> res = new HashMap<>();
        res.put("userList", financeDao.withdrawalList9(params));
        res.put("pageCount", financeDao.pageCount9(params));
        return AjaxResult.success(res);
    }

    @Override
    public AjaxResult<?> update(FinanceVo financeVo) {
//        FinanceVo db = financeDao.selectById(financeVo.getFinanceId());
//        String financeType = db.getFinanceType();
//        if ( financeVo.getFinanceStatus().equals("0") )
//            financeVo.setFinanceStatus("4");
//        else if ( financeType.equals("1") )
//            financeVo.setFinanceStatus("1");
//        else if ( financeType.equals("2") )
//            financeVo.setFinanceStatus("2");
//        else
//            return AjaxResult.error("error,请参考文档,else call me");
        String financeStatus = financeVo.getFinanceStatus();
        if ( financeStatus.equals("0") )
            financeVo.setFinanceStatus("4");
        else if ( financeStatus.equals("1") ){
            financeVo.setFinanceStatus("2");
            BigDecimal examineMoney = financeDao.selectById(financeVo.getFinanceId()).getExamineMoney();
            financeVo.setFinalMoney(examineMoney);
        }
        financeVo.setExamineTime(now());
//        financeVo.setFinalMoney(db.getExamineMoney());
        int i = financeDao.updateById(financeVo);
        return i > 0 ? AjaxResult.success() : AjaxResult.error() ;
    }

    @Override
    public AjaxResult<?> update2(FinanceVo financeVo) {
        financeVo.setLastTime(now());
        financeVo.setFinanceStatus("3");
        FinanceVo vo = financeDao.selectById(financeVo.getFinanceId());
        String userId = vo.getUserId();
        BigDecimal examineMoney = vo.getExamineMoney();
        // 手续费固定 1 %
        BigDecimal divide = examineMoney.divide(new BigDecimal(100));
        BigDecimal finalMoney = examineMoney.subtract(divide);
        financeVo.setFinalMoney(finalMoney);
        UserVo userVo = userDao.selectById(userId);
        //subtract 提现变化
        userVo.setUserDistributionMoney(userVo.getUserDistributionMoney().subtract(examineMoney));
        userVo.setUserCanBe(userVo.getUserCanBe().subtract(examineMoney));
        userVo.setUserCanuseMoney(userVo.getUserCanuseMoney().subtract(examineMoney));
        userVo.setUserTotalMoney(userVo.getUserTotalMoney().subtract(examineMoney));
        userDao.updateById(userVo);
        MoneyVo moneyVo = new MoneyVo();
        moneyVo.setUserId(userId);
        moneyVo.setUserName(userVo.getUserName());
        moneyVo.setUserTel(userVo.getUserTel());
        moneyVo.setAccountType("可提现余额");
        moneyVo.setMoneySourceId("提现");
        moneyVo.setCreateTime(now());
        moneyVo.setMoneyChange(examineMoney);
        moneyVo.setMoneyFinal(userVo.getUserCanuseMoney());
        moneyVo.setMoneyChange(examineMoney);
        moneyVo.setSiteId(userVo.getSiteId());
        moneyVo.setMoneyStatus("1");
        moneyDao.insert(moneyVo);
        int i = financeDao.updateById(financeVo);
        return i > 0 ? AjaxResult.success() : AjaxResult.error() ;
    }

    @Override
    public AjaxResult<?> backInfo(Integer id) {
        return AjaxResult.success(financeDao.selectOne(new MPJLambdaWrapper<FinanceVo>()
                .eq(FinanceVo::getFinanceId,id)
                .selectAll(FinanceVo.class)
                .selectFunc(FuncEnum.CASE_PAYMETHOD,FinanceVo::getPayMethod)
                .selectFunc(FuncEnum.CASE_FSTATUS,FinanceVo::getFinanceStatus)
                .selectAs(UserVo::getUserName,FinanceVo::getUserId)
                .leftJoin(UserVo.class,UserVo::getUserId,FinanceVo::getUserId)));
    }

    @Override
    public AjaxResult<?> payList(Map<String, Object> map) {
        if ( map.get("siteId") == null || "".equals(map.get("siteId")) )
            return AjaxResult.error("siteId is null");
        MPJLambdaWrapper<FinanceVo> mpj = new MPJLambdaWrapper<FinanceVo>()
                .selectAll(FinanceVo.class)
                .eq(FinanceVo::getFinanceType,3)
                .selectFunc(FuncEnum.CASE_PAYMETHOD,FinanceVo::getPayMethod)
                .selectFunc(FuncEnum.CASE_FSTATUS,FinanceVo::getFinanceStatus)
                .selectAs(UserVo::getUserName,FinanceVo::getUserId)
                .leftJoin(UserVo.class,UserVo::getUserId,FinanceVo::getUserId);
        mpj.eq(FinanceVo::getSiteId,map.get("siteId"));
        if ( map.get("createTime") != null && ! "".equals(map.get("createTime")) )//>
            mpj.gt(FinanceVo::getCreateTime,map.get("createTime"));//ge >=
        if ( map.get("createTime2") != null && ! "".equals(map.get("createTime2")) )//>
            mpj.lt(FinanceVo::getCreateTime,map.get("createTime2"));//ge >=
        if ( map.get("lastTime") != null && ! "".equals(map.get("lastTime")) )//>
            mpj.gt(FinanceVo::getLastTime,map.get("lastTime"));//ge >=
        if ( map.get("lastTime2") != null && ! "".equals(map.get("lastTime2")) )//>
            mpj.lt(FinanceVo::getLastTime,map.get("lastTime2"));//ge >=
        if ( map.get("finalMoney") != null && ! "".equals(map.get("finalMoney")) )//>
            mpj.eq(FinanceVo::getFinalMoney,map.get("finalMoney"));//ge >=
        if ( map.get("financeCode") != null && ! "".equals(map.get("financeCode")) )//>
            mpj.like(FinanceVo::getFinanceCode,map.get("financeCode"));//ge >=
        Page<FinanceVo> page = financeDao.selectPage(getPage(map), mpj);
        //-------- 结果处理 --------
        List<FinanceVo> records = page.getRecords();
        long pages = page.getPages();
        //-------- 数据封装 --------
        Map<String,Object> res = new HashMap<>();
        res.put("pageCount",pages);
        res.put("list",records);
        res.put("money",financeDao.selectList(new LambdaQueryWrapper<FinanceVo>()
                .eq(FinanceVo::getFinanceType,3))
                .stream().map(x -> x.getFinalMoney())
                .reduce(BigDecimal.ZERO,BigDecimal::add));
        return AjaxResult.success(res);
    }

    @Override
    public AjaxResult<?> backList2(Map<String, Object> map) {
        if ( map.get("siteId") == null || "".equals(map.get("siteId")) )
            return AjaxResult.error("siteId is null");
        MPJLambdaWrapper<FinanceVo> mpj = new MPJLambdaWrapper<FinanceVo>()
                .selectAll(FinanceVo.class)
                .eq(FinanceVo::getFinanceType,2)
                .selectFunc(FuncEnum.CASE_PAYMETHOD,FinanceVo::getPayMethod)
                .selectFunc(FuncEnum.CASE_FSTATUS,FinanceVo::getFinanceStatus)
                .selectAs(UserVo::getUserName,FinanceVo::getUserId)
                .leftJoin(UserVo.class,UserVo::getUserId,FinanceVo::getUserId)
                .eq(FinanceVo::getSiteId,map.get("siteId"));
        if ( map.get("userId") != null && ! "".equals(map.get("userId")) ){
            List<Integer> integers = userDao.selectList(new LambdaQueryWrapper<UserVo>()
                            .like(UserVo::getUserTel, map.get("userId"))
                            .or(i -> i
                                    .like(UserVo::getUserAccount, map.get("userId")))
                            .or(l -> l
                                    .like(UserVo::getUserName, map.get("userId"))))
                    .stream().map(x -> x.getUserId()).collect(Collectors.toList());
            if ( integers.size() > 0 )
                mpj.in(FinanceVo::getUserId,integers);
            else
                mpj.eq(FinanceVo::getUserId,0);
        }
        if ( map.get("financeCode") != null && ! "".equals(map.get("financeCode")) )
            mpj.like(FinanceVo::getFinanceCode,map.get("financeCode"));
//        if ( map.get("financeStatus") != null && ! "".equals(map.get("financeStatus")) )
//            mpj.eq(FinanceVo::getFinanceStatus,map.get("financeStatus").equals(1) ? "2" : "4" )
//                        .or(i -> {
//                            if ( map.get("financeCode") != null && ! "".equals(map.get("financeCode")) )
//                                mpj.like(FinanceVo::getFinanceCode,map.get("financeCode"));
//                            if ( map.get("createTime") != null && ! "".equals(map.get("createTime")) )//>
//                                mpj.gt(FinanceVo::getCreateTime,map.get("createTime"));//ge >=
//                            if ( map.get("createTime2") != null && ! "".equals(map.get("createTime2")) )//>
//                                mpj.lt(FinanceVo::getCreateTime,map.get("createTime2"));//ge >=
//                            if ( map.get("userId") != null && ! "".equals(map.get("userId")) ){
//                                List<Integer> integers = userDao.selectList(new LambdaQueryWrapper<UserVo>()
//                                                .like(UserVo::getUserTel, map.get("userId"))
//                                                .or(m -> m
//                                                        .like(UserVo::getUserAccount, map.get("userId")))
//                                                .or(l -> l
//                                                        .like(UserVo::getUserName, map.get("userId"))))
//                                        .stream().map(x -> x.getUserId()).collect(Collectors.toList());
//                                if ( integers.size() > 0 )
//                                    mpj.in(FinanceVo::getUserId,integers);
//                                else
//                                    mpj.eq(FinanceVo::getUserId,0);
//                            }
//                            i.eq(FinanceVo::getFinanceStatus,map.get("financeStatus").equals(1) ? "3" : "4" )
//                                    .eq(FinanceVo::getSiteId,map.get("siteId"))
//                                    .eq(FinanceVo::getFinanceType,2);
//                        });
        if ( map.get("financeStatus") != null && ! "".equals(map.get("financeStatus")) )
            mpj.eq(FinanceVo::getFinanceStatus,map.get("financeStatus"));
        if ( map.get("createTime") != null && ! "".equals(map.get("createTime")) )//>
            mpj.gt(FinanceVo::getCreateTime,map.get("createTime"));//ge >=
        if ( map.get("createTime2") != null && ! "".equals(map.get("createTime2")) )//>
            mpj.lt(FinanceVo::getCreateTime,map.get("createTime2"));//ge >=
        Page<FinanceVo> page = financeDao.selectPage(getPage(map), mpj);
        //-------- 结果处理 --------
        List<FinanceVo> records = page.getRecords();
        long pages = page.getPages();
        //-------- 数据封装 --------
        Map<String,Object> res = new HashMap<>();
        res.put("pageCount",pages);
        res.put("list",records);
        List<FinanceVo> list = financeDao.selectList(new LambdaQueryWrapper<FinanceVo>()
                .eq(FinanceVo::getSiteId, map.get("siteId"))
                .eq(FinanceVo::getFinanceType, 2));
        res.put("had",list.stream().filter(x -> x.getFinanceStatus().equals("3")).map(x -> x.getFinalMoney()).reduce(BigDecimal.ZERO,BigDecimal::add));
        res.put("in",list.stream().filter(x -> x.getFinanceStatus().equals("1") || x.getFinanceStatus().equals("2")).map(x -> x.getFinalMoney()).reduce(BigDecimal.ZERO,BigDecimal::add));
//        res.put("in",records);//待审核
        return AjaxResult.success(res);
    }

    private Page<FinanceVo> getPage(Map<String,Object> map){
        if ( map.get("pageIndex") == null || "".equals(map.get("pageIndex")) )
            map.put("pageIndex",1);
        if ( map.get("pageSize") == null || "".equals(map.get("pageSize")) )
            map.put("pageSize",10);
        Long pageIndex = Long.valueOf(map.get("pageIndex").toString());
        Long pageSize = Long.valueOf(map.get("pageSize").toString());
        return new Page<FinanceVo>(pageIndex,pageSize);
    }


}
